﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProtocoloPropietario
{
    public class MensajeProtocolo
    {
        private Protocolo.Header header;
        private Protocolo.Comando cmd;
        private int largo;
        private byte[] datos;

        public byte[] Datos
        {
            get { return datos; }
            set { datos = value; }
        }

        public Protocolo.Header Header
        {
            get { return header; }
            set { header = value; }
        }

        public int Largo
        {
            get { return largo; }
            set { largo = value; }
        }

        public Protocolo.Comando Cmd
        {
            get { return cmd; }
            set { cmd = value; }
        }

        public MensajeProtocolo(Protocolo.Header header, Protocolo.Comando comando, int largoDatos, byte[] datosAMandar)
        {
            this.header = header;
            this.cmd = comando;
            this.largo = largoDatos;
            this.datos = datosAMandar;
        }

        public MensajeProtocolo(Protocolo.Header header, Protocolo.Comando comando, int largoDatos, string datosAMandar)
        {
            this.header = header;
            this.cmd = comando;
            this.largo = largoDatos;
            System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
            this.datos = enc.GetBytes(datosAMandar);
        }

        public byte[] ConvertirAByte()
        {
            int largoCLargo = largo.ToString().Length;
            int largoCom = ((int)cmd).ToString().Length;

            string strLargo = "";
            for (int i = 0; i < 5 - largoCLargo; i++)
            {
                strLargo += "0";
            }
            strLargo += largo.ToString();

            string strCmd;
            if (largoCom == 1)
                strCmd = "0" + ((int)cmd).ToString();
            else
                strCmd = ((int)cmd).ToString();

            string aConvertir = header.ToString() + strCmd + strLargo;
            System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
            byte[] buff = enc.GetBytes(aConvertir);
            byte[] buffFinal = new byte[datos.Length + 10];
            for (int i = 0; i < datos.Length + 10; i++)
            {
                if (i < 10)
                {
                    buffFinal[i] = buff[i];
                }
                else
                {
                    buffFinal[i] = datos[i-10];
                }
            }
            return buffFinal;
        }

        public List<string> InfoDatos()
        {
            string strMensaje = System.Text.Encoding.ASCII.GetString(datos, 0, datos.Length);
            string[] strArr = strMensaje.Split(Protocolo.SEPARADOR);
            List<string> res = new List<string>();
            foreach (string s in strArr)
            {
                if (!s.Equals("")) res.Add(s);
            }
            return res;
        }

        public static MensajeProtocolo ObtenerMensajeProtocolo(byte[] paquete)
        {
            byte[] msj1 = new byte[10];
            byte[] msj2 = new byte[paquete.Length - 10];

            for (int i = 0; i < paquete.Length ; i++)
            {
                if (i < 10)
                {
                    msj1[i] = paquete[i];
                }
                else
                {
                    msj2[i - 10] = paquete[i];
                }
            }
            string strPaquete = System.Text.Encoding.ASCII.GetString(msj1, 0, 10);
            try
            {
                Protocolo.Header msjHead = Protocolo.Header.REQ;
                if (strPaquete.Remove(3) == Protocolo.RES)
                    msjHead = Protocolo.Header.RES;

                strPaquete = strPaquete.Remove(0, 3);
                int msjCmd = Int32.Parse(strPaquete.Remove(2));
                strPaquete = strPaquete.Remove(0, 2);
                int msjLargo = Int32.Parse(strPaquete);

                return new MensajeProtocolo(msjHead, (Protocolo.Comando)msjCmd, msjLargo, msj2);
            }
            catch (Exception)
            {
                return new MensajeProtocolo(Protocolo.Header.RES, Protocolo.Comando.VACIO, 0, msj2);
            }
        }

        public static bool ValidarMensaje(byte[] buff)
        {
            try
            {
                bool ok = true;
                string strPaquete = System.Text.Encoding.ASCII.GetString(buff, 0, buff.Length);
                if (strPaquete.Remove(3) != Protocolo.RES && strPaquete.Remove(3) != Protocolo.REQ) ok = false;
                strPaquete = strPaquete.Remove(0, 3);
                int msjCmd = Int32.Parse(strPaquete.Remove(2));
                strPaquete = strPaquete.Remove(0, 2);
                int msjLargo = Int32.Parse(strPaquete.Remove(5));
                return ok;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }

    public class Protocolo
    {
        public enum Comando
        {
            CLIENTE_CONEXION = 10,
            SERVIDOR_CONEXION_SUBIDA = 11,
            DORMIR = 12,
            SERVIDOR_ACTUALIZAR_BANDA_ANCHA = 13,
            CLIENTE_BAJADA_INICIO = 21,
            CLIENTE_BAJADA_POS = 22,
            CLIENTE_SUBIDA = 31,
            SERVIDOR_SUBIDA = 41,
            SERVIDOR_SUBIDA_INFO = 42,
            SERVIDOR_NOMBRES = 50,
            VACIO =99
        }

        public enum Header { RES, REQ }

        public const string REQ = "REQ";
        public const string RES = "RES";

        public const string OK = "OK";
        public const string ERROR = "Error";

        public const char SEPARADOR = '\0';
    }
}
